<?php

namespace EthanZ\LaravelExt\Server\InternalServer;

use EthanZ\LaravelExt\Exceptions\RpcException;
use EthanZ\LaravelExt\Utils\Tools\ConversionTools;
use EthanZ\LaravelExt\Utils\TraceEntity;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use EthanZ\LaravelExt\Response\Code;
use Illuminate\Support\Arr;

class Service
{


    /**
     * 服务域名
     *
     * @var string
     */
    private string $uri;

    /**
     * 服务地址
     *
     * @var string
     */
    private string $path;

    /**
     * 传输方式
     *
     * @var string
     */
    private string $method = 'get';

    /**
     * 参数
     *
     * @var array
     */
    private array $options = [];


    public function __construct()
    {
        $this->uri = env('APP_URL');

        $this->options['headers']['U-Token'] = request()?->header('U-Token');
    }


    /**
     * 设置地址
     *
     * @param string $path
     *
     * @return Service
     */
    public function setPath(string $path): static
    {
        $this->path = $path;

        return $this;
    }


    /**
     * 设置传输方式
     *
     * @param string $method
     *
     * @return Service
     */
    public function setMethod(string $method): static
    {
        $this->method = $method;

        return $this;
    }


    /**
     * 设置参数
     *
     * @param array $params
     *
     * @return Service
     */
    public function setParams(array $params = []): static
    {
        $this->options['json']                = $params;
        $this->options['json']['admin_debug'] = request('admin_debug');

        return $this;
    }


    /**
     * 实例
     *
     * @return static
     */
    public static function request(): static
    {
        return (new static());
    }


    /**
     * @throws GuzzleException|RpcException
     */
    public function get()
    {
        $url = $this->uri . $this->path;

        $beginTime = microtime(true);
        $response  = (new Client)
            ->request($this->method, $url, $this->options)
            ->getBody()
            ->getContents();

        $data = json_decode($response, true) ?: [];

        // 链路.
        $costTime        = ConversionTools::toNumber((microtime(true) - $beginTime) * 1000);
        $traceEntityData = [
            'info'   => 'excute ' . $costTime . 'ms ' . $this->path,
            'params' => $this->options,
            'data'   => $data,
        ];
        TraceEntity::setAnRpc($traceEntityData);

        if (!$data || !isset($data['code']) || $data['code'] !== Code::$code['SUCCESS']) {
            $code = 'BAS_OTH_001';
            if (isset($data['code']) && $data['code']) {
                $codeData = array_flip(Code::$code);
                $code     = $codeData[$data['code']];
            }

            $msg       = $data['msg'] ?? $response;
            $paramJson = json_encode($this->options, 256);
            $errData   = $data['debug']['error'] ?? [];
            $errData   = Arr::prepend($errData, "$this->path: $paramJson", 'rpc');

            throw new RpcException($code, $msg, $errData);
        }

        return $data['data'];
    }
}
